package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.property.PropertyAdminInfoDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyOperateConditionDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyProjectGetCommunityInfoDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyProjectGetPropertyInfoDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.property.PropertyOperateConditionVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectCommunityInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyProjectUserTypeVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.operate.dao.IOperateAdServeProjectDao;
import com.itlong.cloud.operate.dao.IOperateProjectDao;
import com.itlong.cloud.operate.dao.IOperatePushInfoProjectDao;
import com.itlong.cloud.property.dao.IPropertyBuildInfoDao;
import com.itlong.cloud.property.dao.IPropertyCommunityInfoDao;
import com.itlong.cloud.property.dao.IPropertyPropertyInfoDao;
import com.itlong.cloud.property.dao.IPropertyRoomInfoDao;
import com.itlong.cloud.property.service.IPropertyCommunityInfoService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import com.mysql.jdbc.log.LogUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *     小区信息处理接口实现.
 * </desc>
 *
 * @createDate 2017-10-10
 */
@Service
@RefreshScope
public class PropertyCommunityInfoServiceImpl implements IPropertyCommunityInfoService {

    // 我司商户号
    @Value("${" + PlatformConstants.MCHID + "}")
    public String MCHID;

    @Autowired
    IPropertyCommunityInfoDao iPropertyCommunityInfoDao;//小区信息数据库访问对象

    @Autowired
    IPropertyBuildInfoDao iPropertyBuildInfoDao; //楼栋信息处理接口

    @Autowired
    IPropertyRoomInfoDao iPropertyRoomInfoDao; //房屋信息处理接口

    @Autowired
    IPropertyPropertyInfoDao iPropertyPropertyInfoDao;  //用户保修信息接口

    @Autowired
    IOperateAdServeProjectDao iOperateAdServeProjectDao;  //广告数量统计

    @Autowired
    IOperatePushInfoProjectDao iOperatePushInfoProjectDao; //消息推送统计

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private IOperateProjectDao iOperateProjectDao;  //运营获取单条小区信息 （不含统计信息）

    /**
     * <desc>
     *      查询小区信息及相关统计信息
     * <desc/>
     * @param  propertyProjectGetCommunityInfoDTO 查询小区信息数据传输对象
     * @return 小区相关信息返回对象
     * @author ZiXuan
     * @createDate 2017-10-11
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyProjectCommunityInfoVO getCommunityInfo(PropertyProjectGetCommunityInfoDTO propertyProjectGetCommunityInfoDTO) throws Exception {

        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyProjectGetCommunityInfoDTO);
        params.put("projectId",propertyProjectGetCommunityInfoDTO.getProjectId());
        PropertyProjectCommunityInfoVO datas = iPropertyCommunityInfoDao.getCommunityInfo(propertyProjectGetCommunityInfoDTO.getProjectId(),propertyProjectGetCommunityInfoDTO.getLoginUserId());
        //根据项目编号获取用户类型列表
        List<PropertyProjectUserTypeVO> propertyProjectUserTypeVOList = iPropertyCommunityInfoDao.getProjectUserTypeInfo(propertyProjectGetCommunityInfoDTO.getProjectId());
        for(PropertyProjectUserTypeVO userTypeVO : propertyProjectUserTypeVOList){
            //查询此类型是否被用户关联 若被关联变更不允许删除属性
            if(iPropertyCommunityInfoDao.getUserTypeByRelation(propertyProjectGetCommunityInfoDTO.getProjectId(),userTypeVO.getSpecialType())>0){
                userTypeVO.setSpecialType(0);
            }else{
                userTypeVO.setSpecialType(1);
            }
        }
        datas.setProjectUserTypeVOS(propertyProjectUserTypeVOList);

        //项目楼栋计数
        Integer intBuildCount = iPropertyBuildInfoDao.getRecordCount(params);
        //项目房屋计数
        Integer intRoomCount = iPropertyRoomInfoDao.getRecordCount(params);
        //项目保修计数
        PropertyProjectGetPropertyInfoDTO propertyProjectGetPropertyInfoDTO = new PropertyProjectGetPropertyInfoDTO();
        propertyProjectGetPropertyInfoDTO.setProjectId(propertyProjectGetCommunityInfoDTO.getProjectId());
        List<Integer> propertyTypeList = new ArrayList<>();
        propertyTypeList.add(PropertyInfoTypeEnum.REPAIR_INFO.getType());
        propertyProjectGetPropertyInfoDTO.setPropertyTypeList(propertyTypeList);
        Map<String, Object> repairInfoParams = SqlUtil.convertBeanToMapParams(propertyProjectGetPropertyInfoDTO);
        Integer intRepairInfoCount = iPropertyPropertyInfoDao.getCount(repairInfoParams);
        //项目广告计数
        Integer intAdCount = iOperateAdServeProjectDao.getCount(propertyProjectGetCommunityInfoDTO.getProjectId());
        //项目消息推送
        Integer intPushInfoCount = iOperatePushInfoProjectDao.getCount(propertyProjectGetCommunityInfoDTO.getProjectId());
        // 累计收入总额
        if (datas.getPropertyValueOpen() == 1) {
            // 开通物业增值，统计资金变动明细
            datas.setAggregateIncome(iPropertyCommunityInfoDao.getAggregateIncome(propertyProjectGetCommunityInfoDTO.getProjectId()));
        } else {
            // 未开通物业增值，统计支付订单
            datas.setAggregateIncome(iPropertyCommunityInfoDao.getAggregateIncomeTrade(propertyProjectGetCommunityInfoDTO.getProjectId(), MCHID));
        }
        // 剩余任务，报修数量
        datas.setPropertyTaskCount(iPropertyCommunityInfoDao.getRepairCount(params));
        // 报修明细
        datas.setPropertyTask(iPropertyCommunityInfoDao.getRepairData(params));
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YMDSQL);
//        Calendar c = Calendar.getInstance();
//        c.set(Calendar.DATE, c.get(Calendar.DATE) - 1);
        params.put("yesterday",sdf.format(new Date()));
        // 昨天通行记录次数，与产品讨论，改成今日通行次数
        datas.setYesterdayAccessRecordCount(iPropertyCommunityInfoDao.getYesterdayAccessRecordCount(params));
        // 进出明细
        datas.setAccessRecord(iPropertyCommunityInfoDao.getAccessRecord(params));


        datas.setBuildCount(intBuildCount);
        datas.setRoomCount(intRoomCount);
        datas.setRepairsCount(intRepairInfoCount);
        datas.setAdInfoCount(intAdCount);
        datas.setPushInfoCount(intPushInfoCount);
        datas.setPropertyPhone(iPropertyCommunityInfoDao.getPropertyUserInfoByUserId(propertyProjectGetCommunityInfoDTO.getLoginUserId()).getPropertyPhone());
        return datas;
    }

    /**
     * <desc>
     *      查询物业运营情况
     * </desc>
     *
     * @param propertyOperateConditionDTO 物业运营情况DTO
     * @return 物业运营情况
     * @author wangzhi
     * @createDate 2019/05/24
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyOperateConditionVO getOperateCondition(PropertyOperateConditionDTO propertyOperateConditionDTO) throws Exception {
        String time = propertyOperateConditionDTO.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YYYYMM);
        if (StringUtils.isBlank(time)) {
            time = sdf.format(new Date());
        } else {
            time = sdf.format(sdf.parse(time));
        }
        propertyOperateConditionDTO.setTime(time);
        Map<String,Object> params = SqlUtil.convertBeanToMapParams(propertyOperateConditionDTO);
        PropertyOperateConditionVO propertyOperateConditionVO = new PropertyOperateConditionVO();
        propertyOperateConditionVO.setTime(time);
        // 数字格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        // 项目房屋计数
        Integer intRoomCount = iPropertyRoomInfoDao.getRecordCount(params);
        // 入住房屋计数
        Integer intResideRoomCount = iPropertyRoomInfoDao.getResideRoomCount(params);
        // 空置房屋计数
        Integer intNonRoomCount = intRoomCount - intResideRoomCount;
        intRoomCount = intRoomCount == 0 ? 1 : intRoomCount;
        // 入住比例
        String residePercent = numberFormat.format((float) intResideRoomCount / (float) intRoomCount * 100);
        // 空置比例
        String nonOccupationPercent;
        if (intNonRoomCount >= 1) {
            nonOccupationPercent = numberFormat.format((float) 100 - Float.parseFloat(residePercent));
        } else {
            nonOccupationPercent = "0";
        }
        propertyOperateConditionVO.setResidePercent(residePercent + "%");
        propertyOperateConditionVO.setNonOccupationPercent(nonOccupationPercent + "%");
        // 账单总数
        Integer feeCount = iPropertyCommunityInfoDao.getFeeCount(params);
        // 不计算未缴停车账单，减去
        params.put("feeStatus", 1);
        params.put("type", 3);
        Integer unpaidParkCount = iPropertyCommunityInfoDao.getFeeCount(params);
        feeCount = feeCount - unpaidParkCount;
        feeCount = feeCount == 0 ? 1 : feeCount;
        params.remove("type");
        // 缴费账单总数
        params.put("feeStatus",2);
        Integer paidFeeCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String paidFeePercent = numberFormat.format((float) paidFeeCount / (float) feeCount * 100);
        propertyOperateConditionVO.setPaidFeePercent(paidFeePercent + "%");
        // 未缴账单总数
        params.put("feeStatus",1);
        Integer unpaidFeeCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String unpaidFeePercent = "0";
        if (unpaidFeeCount > 0) {
            unpaidFeePercent = numberFormat.format((float) 100 - Float.parseFloat(paidFeePercent));
        }
        propertyOperateConditionVO.setUnpaidFeePercent(unpaidFeePercent + "%");
        // 缴费物业账单数
        params.put("feeStatus",2);
        params.put("type",1);
        Integer paidPropertyCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String paidPropertyPercent = numberFormat.format((float) paidPropertyCount / (float) feeCount * 100);
        propertyOperateConditionVO.setPaidPropertyPercent(paidPropertyPercent + "%");
        // 缴费维修账单数
        params.put("type",2);
        Integer paidRepairCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String paidRepairPercent = numberFormat.format((float) paidRepairCount / (float) feeCount * 100);
        propertyOperateConditionVO.setPaidRepairPercent(paidRepairPercent + "%");
        // 缴费停车账单数
        params.put("type",3);
        Integer paidParkingCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String paidParkingPercent = numberFormat.format((float) paidParkingCount / (float) feeCount * 100);
        propertyOperateConditionVO.setPaidParkingPercent(paidParkingPercent + "%");
        // 缴费付费临时通行账单数，保证数据对上，用已缴比例减
        params.put("type",5);
        Integer paidMomentCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String paidMomentPercent;
        if (paidMomentCount > 0) {
            paidMomentPercent = numberFormat.format(Float.parseFloat(paidFeePercent) - Float.parseFloat(paidPropertyPercent) - Float.parseFloat(paidRepairPercent) - Float.parseFloat(paidParkingPercent));
        } else {
            paidMomentPercent = "0";
        }
        propertyOperateConditionVO.setPaidMomentPercent(paidMomentPercent + "%");
        // 未缴物业账单数
        params.put("feeStatus",1);
        params.put("type",1);
        Integer unpaidPropertyCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String unpaidPropertyPercent = numberFormat.format((float) unpaidPropertyCount / (float) feeCount * 100);
        propertyOperateConditionVO.setUnpaidPropertyPercent(unpaidPropertyPercent + "%");
        // 未缴维修账单数
        params.put("type",2);
        Integer unpaidRepairCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String unpaidRepairPercent = numberFormat.format((float) unpaidRepairCount / (float) feeCount * 100);
        propertyOperateConditionVO.setUnpaidRepairPercent(unpaidRepairPercent + "%");
        // 未缴停车账单数
//        params.put("type",3);
//        Integer unpaidParkingCount = iPropertyCommunityInfoDao.getFeeCount(params);
//        String unpaidParkingPercent = numberFormat.format((float) unpaidParkingCount / (float) feeCount * 100);
//        propertyOperateConditionVO.setUnpaidParkingPercent(unpaidParkingPercent + "%");
        // 未缴付费临时通行账单数，保证数据对上，用未缴比例减
        params.put("type",5);
        Integer unpaidMomentCount = iPropertyCommunityInfoDao.getFeeCount(params);
        String unpaidMomentPercent;
        if (unpaidMomentCount > 0) {
            unpaidMomentPercent = numberFormat.format(Float.parseFloat(unpaidFeePercent) - Float.parseFloat(unpaidPropertyPercent) - Float.parseFloat(unpaidRepairPercent)/* - Float.parseFloat(unpaidParkingPercent)*/);
        } else {
            unpaidMomentPercent = "0";
        }
        propertyOperateConditionVO.setUnpaidMomentPercent(unpaidMomentPercent + "%");

        // 获取物业管理员手机号码，放此接口中是因为此接口，为物业首页必请求，且耗时短
        PropertyUserInfoPO propertyUserInfoPO = iPropertyCommunityInfoDao.getPropertyUserInfoByUserId(propertyOperateConditionDTO.getLoginUserId());
        propertyOperateConditionVO.setAdministratorPhone(propertyUserInfoPO.getAdministratorPhone());
        return propertyOperateConditionVO;
    }

    /**
     * <desc>
     *      获取通行占比数据
     * </desc>
     *
     * @return 通行占比数据
     * @author wangzhi
     * @createDate 2019/10/16
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<Map<String, Object>> getPassPercent(PropertyProjectGetCommunityInfoDTO propertyProjectGetCommunityInfoDTO) throws Exception {
        // 查询一周内通行方式和对应记录数
        List<Map<String, Object>> typeAndCount = iPropertyCommunityInfoDao.getPassTypeCount(propertyProjectGetCommunityInfoDTO);
        // 总通行记录数，数据库中经过处理总是为第一个元素，且必有
        Integer totalCount = 0;
        List<Map<String, Object>> data = new ArrayList<>();
        // 数字格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        // 当前已计算百分比总和，记录前3百分比之和
        float presentValue = 0f;
        // 设置一个计数器
        int counter = 0;
        for (Map<String, Object> typeAndCountMap : typeAndCount) {
            counter ++;
            // 只计算3个类型
            if (data.size() < 3) {
                String openType = typeAndCountMap.get("openType").toString();
                Integer count = Integer.parseInt(typeAndCountMap.get("count").toString());
                if (openType.equals("totalCount")) {
                    totalCount = count;
                } else {
                    Map<String, Object> passMap = new HashMap<>();
                    // 计算百分比时要规避一个情况，因为四舍五入，则存在相加不等于1的情况，例如总数为3，3个数量分别为1,1,1，此时四舍五入计算百分比均为33.33%，再相加是99.99%，则显示有问题，最后一个应用1减，作为中和值
                    float passPercentValue;
                    // 通行类型大于3中的时候，直接计算，“其他”为中和值(查询数据中包括totalCount，判断大于4)；小于3种时的非最后一种也直接计算，最后一种中和
                    if (typeAndCount.size() > 4 || counter != typeAndCount.size()) {
                        passPercentValue = (float) count / (float) totalCount * 100;
                        presentValue += passPercentValue;
                    } else {
                        passPercentValue = 100f - presentValue;
                    }
                    passMap.put("passName", OpenTypeEnum.getDescription(Integer.parseInt(openType)));
                    passMap.put("passPercent", numberFormat.format(passPercentValue));
                    data.add(passMap);
                }
            }
        }
        // 库中通行类型大于3种，则存在其他，查询数据中包括totalCount，判断大于4
        if (typeAndCount.size() > 4) {
            Map<String, Object> passMap = new HashMap<>();
            passMap.put("passName", "其他");
            passMap.put("passPercent", numberFormat.format(100f - presentValue));
            data.add(passMap);
        }
        return data;
    }

    /**
     * <desc>
     *     修改小区信息
     * </desc>
     *
     * @param paramDTO 修改小区信息数据传输对象
     * @return 受影响的行数
     * @author ZiXuan
     * @createDate 2017-10-23
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer updateCommunityInfo(PropertyProjectGetCommunityInfoDTO paramDTO) throws Exception {

        ProjectPO dataPO = new ProjectPO();
        BeanUtils.copyProperties(paramDTO, dataPO);
        dataPO.setUpdateTime(new Date());
        //处理物业项目用户类型相关逻辑
        List<Map<String, Object>> updateList = new ArrayList<>();
        List<Map<String, Object>> saveList = new ArrayList<>();
        List<String> newUserType = new ArrayList<>();
        List<String> deleteUserType = new ArrayList<>();
        Date date = new Date();
        Integer maxCount = iOperateProjectDao.getUserTypeId(paramDTO.getProjectId());
        //查询未改数据之前的数据
        List<String> oldUserType = iOperateProjectDao.getOldUserTypeId(paramDTO.getProjectId());

        if(paramDTO.getVisitorQrCodeTimesRestrict()!=null){
            for(PropertyProjectUserTypeVO userTypeVO : paramDTO.getProjectUserTypeVOS()){
                //逻辑主键Id不为空则为更新 否则为新增
                if(StringUtils.isNotEmpty(userTypeVO.getUserTypeId())){
                    PropertyProjectUserTypeInfoPO  userTypeInfoPO = new PropertyProjectUserTypeInfoPO();
                    userTypeInfoPO.setUserTypeId(userTypeVO.getUserTypeId());
                    userTypeInfoPO.setUserTypeName(userTypeVO.getUserTypeName());
                    userTypeInfoPO.setUpdateTime(date);
                    updateList.add(SqlUtil.durableData(userTypeInfoPO, PlatformConstants.TABLE_UPDATE));
                    newUserType.add(userTypeVO.getUserTypeId());
                }else{
                    PropertyProjectUserTypeInfoPO  userTypeInfoPOBySave = new PropertyProjectUserTypeInfoPO();
                    userTypeInfoPOBySave.setUserTypeId(LogicIdUtil.bussinessId());
                    userTypeInfoPOBySave.setUserTypeName(userTypeVO.getUserTypeName());
                    userTypeInfoPOBySave.setProjectId(paramDTO.getProjectId());
                    userTypeInfoPOBySave.setSpecialType(maxCount+1);
                    userTypeInfoPOBySave.setCreateTime(date);
                    userTypeInfoPOBySave.setUpdateTime(date);
                    maxCount++;
                    saveList.add(SqlUtil.durableData(userTypeInfoPOBySave, PlatformConstants.TABLE_SAVE));
                }
            }

            for(String oldUserTypeStr : oldUserType){
                if(!newUserType.contains(oldUserTypeStr)){
                    deleteUserType.add(oldUserTypeStr);
                }
            }

            if(deleteUserType!=null && deleteUserType.size()>0){
                for(String deleteUserTypeId : deleteUserType){
                    PropertyProjectUserTypeInfoPO  userTypeInfoPO = new PropertyProjectUserTypeInfoPO();
                    userTypeInfoPO.setUserTypeId(deleteUserTypeId);
                    userTypeInfoPO.setStatus(DataStatusEnum.DELETE.getType());
                    userTypeInfoPO.setUpdateTime(date);
                    updateList.add(SqlUtil.durableData(userTypeInfoPO, PlatformConstants.TABLE_UPDATE));
                }

            }

            if(updateList!=null && updateList.size()>0){
                iOperateProjectDao.batchUpdateByUserType(updateList);
            }

            if(saveList!=null && saveList.size()>0){
                iOperateProjectDao.batchSaveByUserType(saveList);
            }
        }


        //更新前的项目信息
        ProjectPO oldProj = iOperateProjectDao.getOne(paramDTO.getProjectId());
        if(StringUtils.isNotBlank(oldProj.getProjectType())&& "1".equals(oldProj.getProjectType())){
            dataPO.setOfficeAuthMaxNum(paramDTO.getAuthMaxNum());
        }else if(StringUtils.isNotBlank(oldProj.getProjectType())&& "2".equals(oldProj.getProjectType())){
            dataPO.setAuthMaxNum(paramDTO.getOfficeAuthMaxNum());
        }
        if (isProjectInfoChanged(dataPO, oldProj)){
            //项目信息关键变更需通知云对讲
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("projectId",dataPO.getProjectId());
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            changeLogPOS.add(new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_PROJECT, jsonObject, dataPO.getProjectId()));
            JSONObject dataJs = new JSONObject();
            dataJs.put("data",changeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY
            );
            System.out.println(String.format("【%s】通知项目信息变更：projectId-%s",
                    DateUtil.fomatDate1(new Date()), dataPO.getProjectId()));
        }

        if (isProjectInfoChanged(dataPO, oldProj)) {
            //项目信息变更通知云门禁
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("projectId", dataPO.getProjectId());
            List<DeviceBusinessEntranceChangeLogPO> changeLogPOS = new ArrayList<>();
            changeLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_PROJECT, jsonObject, dataPO.getProjectId()));
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", changeLogPOS);

            //发送云门禁指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );
        }
        if (StringUtils.isNotBlank(paramDTO.getPropertyPhone())) {
            PropertyUserInfoPO propertyUserInfoPO = new PropertyUserInfoPO();
            propertyUserInfoPO.setUserId(paramDTO.getLoginUserId());
            propertyUserInfoPO.setPropertyPhone(paramDTO.getPropertyPhone());
            propertyUserInfoPO.setCountryId(paramDTO.getCountryId());
            propertyUserInfoPO.setProvinceId(paramDTO.getProvinceId());
            propertyUserInfoPO.setCityId(paramDTO.getCityId());
            propertyUserInfoPO.setDistrictId(paramDTO.getDistrictId());
            propertyUserInfoPO.setAddress(paramDTO.getAddress());
            if(StringUtils.isNotBlank(paramDTO.getPropertyName())){
                propertyUserInfoPO.setPropertyName(paramDTO.getPropertyName());
            }
            propertyUserInfoPO.setUpdateTime(new Date());
            iPropertyCommunityInfoDao.update(SqlUtil.durableData(propertyUserInfoPO, PlatformConstants.TABLE_UPDATE));
        }

        if(StringUtils.isNotBlank(paramDTO.getPropertyName())){
            List<String> userIdList = iPropertyCommunityInfoDao.getUserIdByProjectId(Collections.singletonList(paramDTO.getProjectId()));
            iPropertyCommunityInfoDao.updatePropertyNameByUserId(userIdList, paramDTO.getPropertyName());
        }

        //开门密码状态变更
        if(dataPO.getOpenPwd()!=null && !dataPO.getOpenPwd().equals(oldProj.getOpenPwd())){
            //推送云对讲指令
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("projectId", dataPO.getProjectId());
            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
            changeLogPOS.add(new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_FULL, jsonObject, dataPO.getProjectId()));
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", changeLogPOS);
            //发送云对讲指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY
            );

            //云门禁
            JSONObject entranceJson = new JSONObject();
            entranceJson.put("projectId", dataPO.getProjectId());
            List<DeviceBusinessEntranceChangeLogPO> entranceChangeLogPOS = new ArrayList<>();
            entranceChangeLogPOS.add(new DeviceBusinessEntranceChangeLogPO(CloudEntranceChangeBusinessEnum.PUSH_RE_LOGIN, entranceJson, dataPO.getProjectId()));
            dataJs.put("data", entranceChangeLogPOS);
            //发送云门禁指令
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                    JSON.toJSONString(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
            );

            //云电梯
            List<DeviceBusinessElevatorChangeLogPO> deviceElevatorChangeLogPOS = new ArrayList<>();
            deviceElevatorChangeLogPOS.add(new DeviceBusinessElevatorChangeLogPO(dataPO.getProjectId(),
                    CloudElevatorChangeBusinessEnum.PUSH_ROOM_FULL,jsonObject.toJSONString()));
            dataJs.put("data",deviceElevatorChangeLogPOS);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        }

        if (dataPO.getNotouchFlag() != null && !dataPO.getNotouchFlag().equals(oldProj.getNotouchFlag())){
            //c.通知APP项目状态变更
            JSONObject dataJsApp = new JSONObject();
            dataJsApp.put("data", dataPO);
            messageSender.send(
                    RabbitMQConstant.RABBITMQ_PROJECT_STATUS_QUEUE,
                    JSON.toJSONString(dataJsApp),
                    RabbitMQConstant.RABBITMQ_HOUSEHOLD_JPUSH_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_PROJECT_STATUS_KEY
            );
        }

        return iPropertyBuildInfoDao.update(SqlUtil.durableData(dataPO, PlatformConstants.TABLE_UPDATE));
    }

    /**
     * <desc>
     *      获取物业账号信息
     * </desc>
     *
     * @param userId 用户id
     * @return 物业账号信息
     * @author wangzhi
     * @createDate 2019/08/08
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyUserInfoPO getPropertyUserInfoByUserId(String userId) throws Exception {
        return iPropertyCommunityInfoDao.getPropertyUserInfoByUserId(userId);
    }

    /**
     * <desc>
     *      修改物业账号信息
     * </desc>
     *
     * @param propertyAdminInfoDTO 物业管理员信息DTO
     * @return 受影响行数
     * @author wangzhi
     * @createDate 2019/08/08
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer update(PropertyAdminInfoDTO propertyAdminInfoDTO) throws Exception {
        Date nowTime = new Date();
        PropertyUserInfoPO propertyUserInfoPO = new PropertyUserInfoPO();
        propertyUserInfoPO.setUserId(propertyAdminInfoDTO.getLoginUserId());
        propertyUserInfoPO.setUpdateTime(nowTime);
        if (propertyAdminInfoDTO.getStep() == 1) {
            propertyUserInfoPO.setAdministratorPhone(propertyAdminInfoDTO.getAdministratorPhone());
            propertyUserInfoPO.setSafetyVerifyTime(nowTime);
        }
        if (propertyAdminInfoDTO.getStep() == 2) {
            propertyUserInfoPO.setPassword(Md5EncryptUtil.md5(propertyAdminInfoDTO.getPassword()));
        }
        if (propertyAdminInfoDTO.getStep() == 3) {
            propertyUserInfoPO.setPropertyName(propertyAdminInfoDTO.getPropertyName());
            propertyUserInfoPO.setPropertyPhone(propertyAdminInfoDTO.getPropertyPhone());
            propertyUserInfoPO.setCountryId(propertyAdminInfoDTO.getCountryId());
            propertyUserInfoPO.setProvinceId(propertyAdminInfoDTO.getProvinceId());
            propertyUserInfoPO.setCityId(propertyAdminInfoDTO.getCityId());
            propertyUserInfoPO.setDistrictId(propertyAdminInfoDTO.getDistrictId());
            propertyUserInfoPO.setAddress(propertyAdminInfoDTO.getAddress());
            ProjectPO projectPO = new ProjectPO();
            projectPO.setProjectId(propertyAdminInfoDTO.getProjectId());
            projectPO.setPosition(propertyAdminInfoDTO.getPosition());
            projectPO.setManagePhone(propertyAdminInfoDTO.getManagePhone());
            projectPO.setCountryId(propertyAdminInfoDTO.getCountryId());
            projectPO.setProvinceId(propertyAdminInfoDTO.getProvinceId());
            projectPO.setCityId(propertyAdminInfoDTO.getCityId());
            projectPO.setDistrictId(propertyAdminInfoDTO.getDistrictId());
            projectPO.setAddress(propertyAdminInfoDTO.getAddress());
            projectPO.setCommunityName(propertyAdminInfoDTO.getCommunityName());
            projectPO.setUpdateTime(nowTime);
            iPropertyCommunityInfoDao.update(SqlUtil.durableData(projectPO, PlatformConstants.TABLE_UPDATE));
        }
        if (propertyAdminInfoDTO.getStep() == 4) {
            propertyUserInfoPO.setSafetyVerifyTime(nowTime);
        }
        Map<String, Object> map = SqlUtil.durableData(propertyUserInfoPO, PlatformConstants.TABLE_UPDATE);
        if (StringUtils.isBlank(propertyUserInfoPO.getUserId()) && propertyAdminInfoDTO.getStep() == 2) {
            // 没有userId的修改密码时为找回密码，以userName更新密码
            map.put("mark", "user_name");
            map.put("markValue", propertyAdminInfoDTO.getUserName());
        }
        if (StringUtils.isBlank(propertyUserInfoPO.getUserId()) && propertyAdminInfoDTO.getStep() == 4) {
            // 没有userId的校验验证码为找回密码时的校验，以userName更新最后一次安全验证时间
            map.put("mark", "user_name");
            map.put("markValue", propertyAdminInfoDTO.getUserName());
        }
        return iPropertyCommunityInfoDao.update(map);
    }

    private boolean isProjectInfoChanged(ProjectPO newProj, ProjectPO oldProj){
        /*项目关键信息是否变更
        * 工程密码，物业联系方式
        * */
        if ((newProj.getProjectName() != null && !newProj.getProjectName().equals(oldProj.getProjectName()))
                ||((newProj.getEngineerCode() != null && !newProj.getEngineerCode().equals(oldProj.getEngineerCode())))
                ||(newProj.getManagePhone() != null && !newProj.getManagePhone().equals(oldProj.getManagePhone()))
                ) {
            return true;
        }
        return false;
    }

    /**
     * <desc>
     *     保存收费间隔时间
     * <desc/>
     *
     * @param  projectId  项目编号
     * @param  intervalTime  间隔时间
     * @param  type  类型 1保存 2获取
     * @param  warningTimes  预警次数
     * @return  MessageVO 标准格式化响应结果
     * @author JuGuang.S
     * @createDate 2020/07/15
     */
    public Map<String,Object> saveFeeIntervalTime(String projectId, String intervalTime,Integer type,Integer warningTimes) throws Exception{
        JSONArray jsonArrayCloudElevator = new JSONArray();
        List<DeviceBusinessElevatorChangeLogPO> deviceBusinessChangeLogPOS = new ArrayList<>();
        if(type==1){
            Map<String,Object> map =  iPropertyCommunityInfoDao.getFeeIntervalTimeByProjectId(projectId);
            if(!map.isEmpty() && !(map.get("warningTimes")+"").equals(warningTimes+"")){
                //查询本项目下的所有云电梯设备
                List<String> list = iPropertyCommunityInfoDao.getCloudElevatorByProjectId(projectId);
                if(!list.isEmpty()){
                    for(String sn : list){

                        JSONObject jsonObjectCloudElevator = new JSONObject();
                        jsonObjectCloudElevator.put("deviceUnique", StringHandlerUtil.getElevatorDeviceUniqueBySn(sn));
                        jsonObjectCloudElevator.put("projectId", projectId);
                        jsonObjectCloudElevator.put("sn", sn);
                        jsonArrayCloudElevator.add(jsonObjectCloudElevator);
                    }
                }

                //如果预警次数有变更，则向云电梯推送重启指令
                if (!jsonArrayCloudElevator.isEmpty()) {
                    DeviceBusinessElevatorChangeLogPO elevatorChangeLogPO = new DeviceBusinessElevatorChangeLogPO(projectId, CloudElevatorChangeBusinessEnum.PUSH_DEVICE_INFO,jsonArrayCloudElevator.toJSONString());
                    deviceBusinessChangeLogPOS.add(elevatorChangeLogPO);
                    //推送云电梯重启指令
                    if(deviceBusinessChangeLogPOS != null && !deviceBusinessChangeLogPOS.isEmpty()){
                        this.pushElevator(deviceBusinessChangeLogPOS);
                    }
                }
            }
            iPropertyCommunityInfoDao.saveFeeIntervalTime(projectId,intervalTime,warningTimes);
            return new HashMap<>();
        }else{
            return iPropertyCommunityInfoDao.getFeeIntervalTimeByProjectId(projectId);
        }
    }

    /**
     * <desc>
     *      向设备推送设备云电梯指令
     * <desc/>
     *
     * @param   changeLogPOS     云电梯变更指令集合
     * @author Jiaqi.X
     * @createDate 2017/12/1
     */
    public void pushElevator(List<DeviceBusinessElevatorChangeLogPO> changeLogPOS) throws Exception {
        // 添加硬件推送指令
        if (!changeLogPOS.isEmpty()) {
            JSONObject dataJs = new JSONObject();
            dataJs.put("data", changeLogPOS);
            //云电梯
            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                    JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
        }
    }
}
